/*
 *  Copyright 2005 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.apache.ibatis.ibator.api;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.ibator.api.dom.OutputUtilities;
import org.apache.ibatis.ibator.api.dom.java.FullyQualifiedJavaType;
import org.apache.ibatis.ibator.api.dom.java.Interface;
import org.apache.ibatis.ibator.api.dom.java.Method;
import org.apache.ibatis.ibator.api.dom.java.TopLevelClass;
import org.apache.ibatis.ibator.config.IbatorConfiguration;
import org.apache.ibatis.ibator.config.IbatorContext;
import org.apache.ibatis.ibator.config.MergeConstants;
import org.apache.ibatis.ibator.exception.InvalidConfigurationException;
import org.apache.ibatis.ibator.exception.ShellException;
import org.apache.ibatis.ibator.internal.DefaultShellCallback;
import org.apache.ibatis.ibator.internal.IbatorObjectFactory;
import org.apache.ibatis.ibator.internal.NullProgressCallback;
import org.apache.ibatis.ibator.internal.XmlFileMergerJaxp;
import org.apache.ibatis.ibator.internal.util.ClassloaderUtility;
import org.apache.ibatis.ibator.internal.util.messages.Messages;
import org.apache.ibatis.ibator.pluginpo.ActionPO;
import org.apache.ibatis.ibator.pluginpo.Bean;
import org.apache.ibatis.ibator.pluginpo.BeanProperty;
import org.apache.ibatis.ibator.pluginpo.ConfigBean;
import org.apache.ibatis.ibator.pluginpo.GenRule;
import org.apache.ibatis.ibator.pluginpo.NewMethod;
import org.apache.ibatis.ibator.pluginpo.ServiceImplPO;
import org.apache.ibatis.ibator.resource.Resource;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * This class is the main interface to the ibator for iBATIS code generator. A
 * typical execution of the tool involves these steps:
 * 
 * <ol>
 * <li>Create an IbatorConfiguration object. The IbatorConfiguration can be the
 * result of a parsing the XML configuration file, or it can be created solely
 * in Java.</li>
 * <li>Create an Ibator object</li>
 * <li>Call one of the generate() methods</li>
 * </ol>
 * 
 * @see org.apache.ibatis.ibator.config.xml.IbatorConfigurationParser
 * 
 * @author Jeff Butler
 */
public class Ibator {

	private IbatorConfiguration ibatorConfiguration;

	private ShellCallback shellCallback;

	private List<GeneratedJavaFile> generatedJavaFiles;

	private List<GeneratedXmlFile> generatedXmlFiles;
	/**
	 * this properties is new add by zzg
	 */
	private List<GeneratedExtendFile> generatedExtendFiles;

	private List<String> warnings;

	private Set<String> projects;

	/**
	 * Constructs an Ibator object.
	 * 
	 * @param ibatorConfiguration
	 *            The configuration for this run of ibator
	 * @param shellCallback
	 *            an instance of a ShellCallback interface. You may specify
	 *            <code>null</code> in which case ibator will use the
	 *            DefaultShellCallback.
	 * @param warnings
	 *            Any warnings generated during execution will be added to this
	 *            list. Warnings do not affect the running of the tool, but they
	 *            may affect the results. A typical warning is an unsupported
	 *            data type. In that case, the column will be ignored and
	 *            generation will continue. ibator will only add Strings to the
	 *            list. You may specify <code>null</code> if you do not want
	 *            warnings returned.
	 * @throws InvalidConfigurationException
	 *             if the specified configuration is invalid
	 */
	public Ibator(IbatorConfiguration ibatorConfiguration, ShellCallback shellCallback, List<String> warnings)
			throws InvalidConfigurationException {
		super();
		if (ibatorConfiguration == null) {
			throw new IllegalArgumentException(Messages.getString("RuntimeError.2")); //$NON-NLS-1$
		} else {
			this.ibatorConfiguration = ibatorConfiguration;
		}

		if (shellCallback == null) {
			this.shellCallback = new DefaultShellCallback(false);
		} else {
			this.shellCallback = shellCallback;
		}

		if (warnings == null) {
			this.warnings = new ArrayList<String>();
		} else {
			this.warnings = warnings;
		}
		generatedJavaFiles = new ArrayList<GeneratedJavaFile>();
		generatedXmlFiles = new ArrayList<GeneratedXmlFile>();
		generatedExtendFiles = new ArrayList<GeneratedExtendFile>();
		projects = new HashSet<String>();

		this.ibatorConfiguration.validate();
	}

	/**
	 * This is the main method for generating code. This method is long running,
	 * but progress can be provided and the method can be cancelled through the
	 * ProgressCallback interface. This version of the method runs all
	 * configured contexts.
	 * 
	 * @param callback
	 *            an instance of the ProgressCallback interface, or
	 *            <code>null</code> if you do not require progress information
	 * @throws SQLException
	 * @throws IOException
	 * @throws InterruptedException
	 *             if the method is cancelled through the ProgressCallback
	 */
	public void generate(ProgressCallback callback) throws SQLException, IOException, InterruptedException {
		generate(callback, null, null);
	}

	/**
	 * This is the main method for generating code. This method is long running,
	 * but progress can be provided and the method can be cancelled through the
	 * ProgressCallback interface.
	 * 
	 * @param callback
	 *            an instance of the ProgressCallback interface, or
	 *            <code>null</code> if you do not require progress information
	 * @param contextIds
	 *            a set of Strings containing context ids to run. Only the
	 *            contexts with an id specified in this list will be run. If the
	 *            list is null or empty, than all contexts are run.
	 * @throws InvalidConfigurationException
	 * @throws SQLException
	 * @throws IOException
	 * @throws InterruptedException
	 *             if the method is cancelled through the ProgressCallback
	 */
	public void generate(ProgressCallback callback, Set<String> contextIds) throws SQLException, IOException,
			InterruptedException {
		generate(callback, contextIds, null);
	}

	/**
	 * This is the main method for generating code. This method is long running,
	 * but progress can be provided and the method can be cancelled through the
	 * ProgressCallback interface.
	 * 
	 * @param callback
	 *            an instance of the ProgressCallback interface, or
	 *            <code>null</code> if you do not require progress information
	 * @param contextIds
	 *            a set of Strings containing context ids to run. Only the
	 *            contexts with an id specified in this list will be run. If the
	 *            list is null or empty, than all contexts are run.
	 * @param fullyQualifiedTableNames
	 *            a set of table names to generate. The elements of the set must
	 *            be Strings that exactly match what's specified in the
	 *            configuration. For example, if table name = "foo" and schema =
	 *            "bar", then the fully qualified table name is "foo.bar". If
	 *            the Set is null or empty, then all tables in the configuration
	 *            will be used for code generation.
	 * @throws InvalidConfigurationException
	 * @throws SQLException
	 * @throws IOException
	 * @throws InterruptedException
	 *             if the method is cancelled through the ProgressCallback
	 */
	public void generate(ProgressCallback callback, Set<String> contextIds, Set<String> fullyQualifiedTableNames)
			throws SQLException, IOException, InterruptedException {

		if (callback == null) {
			callback = new NullProgressCallback();
		}

		generatedJavaFiles.clear();
		generatedXmlFiles.clear();
		generatedExtendFiles.clear();

		// calculate the contexts to run
		List<IbatorContext> contextsToRun;
		if (contextIds == null || contextIds.size() == 0) {
			contextsToRun = ibatorConfiguration.getIbatorContexts();
		} else {
			contextsToRun = new ArrayList<IbatorContext>();
			for (IbatorContext ibatorContext : ibatorConfiguration.getIbatorContexts()) {
				if (contextIds.contains(ibatorContext.getId())) {
					contextsToRun.add(ibatorContext);
				}
			}
		}

		int totalSteps = 0;

		for (IbatorContext ibatorContext : contextsToRun) {
			totalSteps += ibatorContext.getTotalSteps();
		}

		callback.setNumberOfSubTasks(totalSteps);

		// setup custom classloader
		ClassLoader classLoader = ClassloaderUtility.getCustomClassloader(ibatorConfiguration.getClassPathEntries());
		IbatorObjectFactory.setClassLoader(classLoader);

		// now run the generates...
		for (IbatorContext ibatorContext : contextsToRun) {
			ibatorContext.generateFiles(callback, generatedJavaFiles, generatedXmlFiles, warnings,
					fullyQualifiedTableNames);
		}

		for (GeneratedXmlFile gxf : generatedXmlFiles) {
			projects.add(gxf.getTargetProject());

			File targetFile;
			String source;
			try {
				File directory = shellCallback.getDirectory(gxf.getTargetProject(), gxf.getTargetPackage(), warnings);
				targetFile = new File(directory, gxf.getFileName());
				if (targetFile.exists()) {
					if (gxf.isMergeable()) {
						source = XmlFileMergerJaxp.getMergedSource(gxf, targetFile);
					} else {
						source = gxf.getFormattedContent();
						targetFile = getUniqueFileName(directory, gxf.getFileName());
						warnings.add(Messages.getString("Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$
					}
				} else {
					source = gxf.getFormattedContent();
				}
			} catch (ShellException e) {
				warnings.add(e.getMessage());
				continue;
			}

			writeFile(targetFile, source);
		}

		for (GeneratedJavaFile gjf : generatedJavaFiles) {
			projects.add(gjf.getTargetProject());

			File targetFile;
			String source;
			try {
				File directory = shellCallback.getDirectory(gjf.getTargetProject(), gjf.getTargetPackage(), warnings);
				targetFile = new File(directory, gjf.getFileName());
				if (targetFile.exists()) {
					if (shellCallback.mergeSupported() && gjf.isMergeable()) {
						source = shellCallback.mergeJavaFile(gjf, MergeConstants.OLD_JAVA_ELEMENT_TAGS, warnings);
					} else {
						source = gjf.getFormattedContent();
						targetFile = getUniqueFileName(directory, gjf.getFileName());
						warnings.add(Messages.getString("Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$
					}
				} else {
					source = gjf.getFormattedContent();
				}

				writeFile(targetFile, source);
			} catch (ShellException e) {
				warnings.add(e.getMessage());
			}
		}

		Boolean configoverwrite = Boolean.parseBoolean((String) ibatorConfiguration.getProperties().get(
				"extends.configfile.overwrite"));
		Boolean javaoverwrite = Boolean.parseBoolean((String) ibatorConfiguration.getProperties().get(
				"extends.javafile.overwrite"));
		Boolean ftloverwrite = Boolean.parseBoolean((String) ibatorConfiguration.getProperties().get(
				"extends.ftlfile.overwrite"));

		GenRule genRule = new GenRule();

		Map rootMap = null;

		String directForTemp = null;
		String targetSrc = null;
		String outPutName = null;
		String templetName = null;
		List<ConfigBean> serviceList = new ArrayList<ConfigBean>();
		List<ConfigBean> actionList = new ArrayList<ConfigBean>();
		String scope = (String) ibatorConfiguration.getProperties().get("extends.spring.bean.scope");
		System.out.println("info: thread :"+Thread.currentThread());
		System.out.println("info: thread id:"+Thread.currentThread().getId());
		InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("org/extendsProperties.properties");

		byte[] b=new byte[in.available()];
		
		in.read(b);
		
		String ss=new String(b);
		
		System.out.println(ss);
		
		
		
//		System.out.println("info: thread classloader:"+Thread.currentThread().getContextClassLoader().getResourceAsStream("org/extendsProperties.properties"));
//		System.out.println("info: thread classloader2:"+Thread.currentThread().getContextClassLoader().getParent());
//		System.out.println("info: thread classloader2:"+Thread.currentThread().getContextClassLoader().getResource("org/extendsProperties.properties").getPath());
//		System.out.println("info: thread classloader3:"+Thread.currentThread().getContextClassLoader().getParent().getResource(""));
//		System.out.println("info: thread getClassLoader:"+Thread.currentThread().getClass().getClassLoader());
//		try {
//			System.out.println("info: thread111:"+Thread.currentThread().getContextClassLoader().loadClass("org.apache.ibatis.ibator.pluginpo.ActionPO"));
//		} catch (ClassNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		System.out.println("info: this.getClass():"+Ibator.class.getClassLoader().getResource("."));
		String url=	"";
		for (Interface inf : Resource.interfaces) {
			List<Method> mths = inf.getMethods();

			/**
			 * 根据dao的方法根据规则转换成service的方法 ,暂时定死，有时间可以改写成可配置
			 */
			List<NewMethod> methods = new ArrayList<NewMethod>();
			String aliasName = inf.getType().getShortName().substring(0,
					inf.getType().getShortName().lastIndexOf("DAO"));

			for (Method mtd : mths) {
				NewMethod nem = new NewMethod();
				if (mtd.getName().equals("insert" + GenRule.capFirst(aliasName))) {
					nem.setMethodName("create");
				} else if (mtd.getName().equals("update" + GenRule.capFirst(aliasName) + "ByPrimaryKey")) {
					nem.setMethodName("update");
				} else if (mtd.getName().equals("select" + GenRule.capFirst(aliasName) + "ByPrimaryKey")) {
					nem.setMethodName("get");
				} else if (mtd.getName().equals("select" + GenRule.capFirst(aliasName) + "ByExample")) {
					nem.setMethodName("list");
				} else if (mtd.getName().equals("delete" + GenRule.capFirst(aliasName) + "ByPrimaryKey")) {
					nem.setMethodName("delete");
				}
				else if (mtd.getName().equals("select" + GenRule.capFirst(aliasName) + "ByExampleWithBLOBs")) {
					nem.setMethodName("list");
				}else if (mtd.getName().equals("update" + GenRule.capFirst(aliasName) + "ByPrimaryKeyWithBLOBs")) {
					nem.setMethodName("update");
				}else {
					nem.setMethodName(mtd.getName());
				}

				nem.setMethod(mtd);
				methods.add(nem);

			}

			ServiceImplPO serviceImplPO = new ServiceImplPO();

			serviceImplPO.setName(GenRule.genNameByType(aliasName, "serviceI"));

			// serviceImplPO.setInterfaceName(inf.getType().getShortName()+
			// "Service");
			serviceImplPO.setMethods(methods);
			List<String> imports = new ArrayList<String>();

			for (FullyQualifiedJavaType fqjt : inf.getImportedTypes()) {
				if (fqjt.isExplicitlyImported()) {
					imports.add(fqjt.getFullyQualifiedName());
				}
			}

			imports.add(inf.getType().getFullyQualifiedName());

			serviceImplPO.setImports(imports);
			String packageName = (String) ibatorConfiguration.getProperties().get("extends.spring.serviceI.package");
			String interfacePackage = packageName;
			serviceImplPO.setPackageName(packageName);

			rootMap = new HashMap();
			rootMap.put("serviceInterface", serviceImplPO);
	
		
//			url=	Thread.currentThread().getContextClassLoader().getResource("codeTemplete/service").getPath();
			
			directForTemp = "/codeTemplete/service/";
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.spring.serviceI.targetSrc");
			outPutName = serviceImplPO.getName() + ".java";
			templetName = (String) ibatorConfiguration.getProperties().get("extends.service.templete.Iname");

			// 生成Service .java

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, packageName, outPutName, templetName,
						warnings, javaoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			/**
			 * 生成serviceImpl .java
			 */
			packageName = (String) ibatorConfiguration.getProperties().get("extends.spring.service.package");

			serviceImplPO.setPackageName(packageName);
			serviceImplPO.setInterfaceName(GenRule.genNameByType(aliasName, "serviceI"));
			serviceImplPO.setName(GenRule.genNameByType(aliasName, "service"));
			serviceImplPO.setAlias(aliasName);
			imports.add(interfacePackage + "." + GenRule.genNameByType(aliasName, "serviceI"));

			Bean bean = new Bean();

			bean.setPoType("");
			bean.setType(inf.getType().getShortName());
			bean.setName(inf.getType().getShortName());

			bean.setMethods(methods);
			List<Bean> beans = new ArrayList<Bean>();
			beans.add(bean);
			serviceImplPO.setBeans(beans);

			/**
			 * 为生成 app-service.xm 准备
			 */

			ConfigBean cfbean = new ConfigBean();
			cfbean.setBeanName(GenRule.uncapFirst(serviceImplPO.getName()));
			cfbean.setBeanFullName(serviceImplPO.getPackageName() + "." + serviceImplPO.getName());
			BeanProperty beanProperty = new BeanProperty();
			beanProperty.setName(inf.getType().getShortName());
			beanProperty.setRef(inf.getType().getShortName());
			List<BeanProperty> properties = new ArrayList<BeanProperty>();
			properties.add(beanProperty);
			cfbean.setProperties(properties);
			cfbean.setScope(scope);
			serviceList.add(cfbean);

			rootMap = new HashMap();
			rootMap.put("serviceImpl", serviceImplPO);
			rootMap.put("genRule", new GenRule());

//			directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.spring.service.targetSrc");
			outPutName = serviceImplPO.getName() + ".java";
			templetName = (String) ibatorConfiguration.getProperties().get("extends.service.templete.name");

			// ���ServiceImpl

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, packageName, outPutName, templetName,
						warnings, javaoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			/**
			 * 生成 action .java
			 */

			ActionPO po = new ActionPO();
			po.setBaseAlia(aliasName);
			imports.add(interfacePackage + "." + GenRule.genNameByType(aliasName, "serviceI"));
			po.setImports(imports);
			packageName = (String) ibatorConfiguration.getProperties().get("extends.struts.package");
			po.setPackageName(packageName);

			// cfg.setDirectoryForTemplateLoading(new File(
			// "D:\\spaces\\my\\3.4\\CodeGen\\src\\main\\resources\\codeTemplete\\struts2"
			// ));

			ConfigBean acbean = new ConfigBean();
			acbean.setBaseAlias(aliasName);
			acbean.setBeanName(GenRule.genNameByType(aliasName, "action"));
			acbean.setBeanFullName(po.getPackageName() + "."
					+ GenRule.capFirst(GenRule.genNameByType(aliasName, "action")));
			beanProperty = new BeanProperty();
			beanProperty.setName(GenRule.genNameByType(aliasName, "service"));
			beanProperty.setRef(GenRule.genNameByType(aliasName, "service"));
			properties = new ArrayList<BeanProperty>();
			properties.add(beanProperty);
			acbean.setProperties(properties);
			acbean.setScope(scope);
			actionList.add(acbean);

			rootMap = new HashMap();
			rootMap.put("action", po);
			rootMap.put("genRule", new GenRule());

//           url=	Thread.currentThread().getContextClassLoader().getResource("codeTemplete/struts2").getPath();
			
			directForTemp = "/codeTemplete/struts2/";
//			directForTemp = (String) ibatorConfiguration.getProperties().get("extends.struts.templete.path");
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.struts.targetSrc");
			outPutName = GenRule.genNameByType(aliasName, "action") + ".java";
			templetName = (String) ibatorConfiguration.getProperties().get("extends.struts.templete.name");

			// ���ServiceImpl

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, packageName, outPutName, templetName,
						warnings, javaoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		}

		List<ConfigBean> daoList = new ArrayList<ConfigBean>();

		if (Resource.topLevelClass != null && Resource.topLevelClass.size() > 0) {
			for (TopLevelClass tlc : Resource.topLevelClass) {
				ConfigBean bean = new ConfigBean();
				bean.setBeanName(tlc.getType().getShortName()
						.substring(0, tlc.getType().getShortName().indexOf("Impl")));
				bean.setBeanFullName(tlc.getType().getFullyQualifiedName());
				BeanProperty beanProperty = new BeanProperty();
				beanProperty.setName("sqlMapClient");
				beanProperty.setRef("sqlMapClient");
				List<BeanProperty> properties = new ArrayList<BeanProperty>();
				properties.add(beanProperty);
				bean.setProperties(properties);
				bean.setScope(scope);
				daoList.add(bean);
			}
		}
		if (daoList != null && serviceList != null && actionList != null) {

			rootMap = new HashMap();
			rootMap.put("beans", daoList);
			rootMap.put("genRule", new GenRule());
//			 url=	Thread.currentThread().getContextClassLoader().getResource("codeTemplete/service").getPath();
				
			directForTemp = "/codeTemplete/service/";
//			directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.dao.config.path");
			outPutName = (String) ibatorConfiguration.getProperties().get("extends.dao.config.name");
			templetName = (String) ibatorConfiguration.getProperties().get("extends.dao.config.templete.name");

			// 生成applicationContext-dao.xml

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			rootMap = new HashMap();
			rootMap.put("beans", serviceList);
			rootMap.put("genRule", new GenRule());

//			directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.dao.config.path");
			outPutName = (String) ibatorConfiguration.getProperties().get("extends.spring.service.config.name");
			templetName = (String) ibatorConfiguration.getProperties().get("extends.dao.config.templete.name");

			// 生成applicationContext-service.xml

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

//			directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.dao.config.path");
			outPutName = (String) ibatorConfiguration.getProperties().get("extends.struts.bean.config.name");
			templetName = (String) ibatorConfiguration.getProperties().get("extends.dao.config.templete.name");
			String pathPrefix = (String) ibatorConfiguration.getProperties().get(
					"extends.struts.configxml.template.pathPrefix");
			String configxmlPackage = (String) ibatorConfiguration.getProperties().get(
					"extends.struts.configxml.packageName");

			rootMap = new HashMap();
			rootMap.put("beans", actionList);
			rootMap.put("genRule", new GenRule());
			rootMap.put("pathPrefix", pathPrefix);
			rootMap.put("packageName", configxmlPackage);

			// 生成applicationContext-action.xml

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
//			 url=	Thread.currentThread().getContextClassLoader().getResource("codeTemplete/struts2").getPath();
				
			directForTemp = "/codeTemplete/struts2/";
//			directForTemp = (String) ibatorConfiguration.getProperties().get("extends.struts.templete.path");
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.struts.config.path");
			outPutName = (String) ibatorConfiguration.getProperties().get("extends.struts.action.config.name");
			templetName = (String) ibatorConfiguration.getProperties().get("extends.struts.config.templete.name");

			// 生成struts.xml

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		}

		for (IntrospectedTable tb : Resource.introspectedTables) {

//			 url=	Thread.currentThread().getContextClassLoader().getResource("codeTemplete/struts2").getPath();
				
			directForTemp = "/codeTemplete/struts2/";
//			directForTemp = (String) ibatorConfiguration.getProperties().get("extends.struts.templete.path");
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.page.targetSrc");
			String pathPrefix = (String) ibatorConfiguration.getProperties().get(
					"extends.struts.configxml.template.pathPrefix");
			String configxmlPackage = (String) ibatorConfiguration.getProperties().get(
					"extends.struts.configxml.packageName");
			outPutName = GenRule.uncapFirst(GenRule.genNameByType(tb.getBaseRecordType().getShortName(), "createPage"));

			templetName = "create-page.ftl";

			rootMap = new HashMap();
			rootMap.put("table", tb);
			rootMap.put("pathPrefix", pathPrefix);
			rootMap.put("packageName", configxmlPackage);
			rootMap.put("genRule", new GenRule());

			// createPage.ftl

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, pathPrefix + "." + configxmlPackage,
						outPutName, templetName, warnings, ftloverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			outPutName = GenRule.uncapFirst(GenRule.genNameByType(tb.getBaseRecordType().getShortName(), "listPage"));

			templetName = "list-page.ftl";

			// listPage.ftl

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, pathPrefix + "." + configxmlPackage,
						outPutName, templetName, warnings, ftloverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			outPutName = GenRule.uncapFirst(GenRule.genNameByType(tb.getBaseRecordType().getShortName(), "updatePage"));

			templetName = "detail-page.ftl";

			// ServiceImpl

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, pathPrefix + "." + configxmlPackage,
						outPutName, templetName, warnings, ftloverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			// 生成验证文件
			targetSrc = (String) ibatorConfiguration.getProperties().get("extends.struts.targetSrc");
			String packageName = (String) ibatorConfiguration.getProperties().get("extends.struts.package");
			outPutName = GenRule.genNameByType(tb.getBaseRecordType().getShortName(), "action") + "-" + "create"
					+ tb.getBaseRecordType().getShortName() + "-validation.xml";
			templetName = "validation-create-update.xml.ftl";
			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, packageName, outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			outPutName = GenRule.genNameByType(tb.getBaseRecordType().getShortName(), "action") + "-" + "update"
					+ tb.getBaseRecordType().getShortName() + "-validation.xml";

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, packageName, outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			templetName = "validation-get-delete.xml.ftl";

			outPutName = GenRule.genNameByType(tb.getBaseRecordType().getShortName(), "action") + "-" + "get"
					+ tb.getBaseRecordType().getShortName() + "-validation.xml";

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, packageName, outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			outPutName = GenRule.genNameByType(tb.getBaseRecordType().getShortName(), "action") + "-" + "delete"
					+ tb.getBaseRecordType().getShortName() + "-validation.xml";

			try {
				genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, packageName, outPutName, templetName,
						warnings, configoverwrite);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		}

		// 生成applicationContext.xml
		
		rootMap = new HashMap();
		rootMap.put("dataAccessContext", "dataAccessContext-local.xml");
		rootMap.put("applicationContextDao", (String) ibatorConfiguration.getProperties().get("extends.dao.config.name"));
		rootMap.put("applicationContextService", (String) ibatorConfiguration.getProperties().get("extends.spring.service.config.name"));
		rootMap.put("applicationContextAction", (String) ibatorConfiguration.getProperties().get("extends.struts.bean.config.name"));

//		 url=	Thread.currentThread().getContextClassLoader().getResource("codeTemplete/service").getPath();
			
		directForTemp = "/codeTemplete/service/";
//		directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
		targetSrc = (String) ibatorConfiguration.getProperties().get("extends.dao.config.path");
		outPutName = "applicationContext.xml";
		templetName = "applicationContext.xml.ftl";

		try {
			genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName, warnings,
					configoverwrite);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// 生成dataAccessContext.xml
//		directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
		targetSrc = (String) ibatorConfiguration.getProperties().get("extends.dao.config.path");
		outPutName = "dataAccessContext-local.xml";
		templetName = "dataAccessContext-local.xml.ftl";

		try {
			genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName, warnings,
					configoverwrite);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// 生成jdbc.properties
		
		
//		directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
		targetSrc = (String) ibatorConfiguration.getProperties().get("extends.dao.config.path");
		outPutName = "jdbc.properties";
		templetName = "jdbc.properties.ftl";
		rootMap = new HashMap();
		rootMap.put("driverClassName", (String) ibatorConfiguration.getProperties().get("jdbc.driverClassName"));
		rootMap.put("url", (String) ibatorConfiguration.getProperties().get("jdbc.url"));
		rootMap.put("username", (String) ibatorConfiguration.getProperties().get("jdbc.username"));
		rootMap.put("password", (String) ibatorConfiguration.getProperties().get("jdbc.password"));

		try {
			genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName, warnings,
					configoverwrite);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// 生成log4j.xml

//		directForTemp = (String) ibatorConfiguration.getProperties().get("extends.service.templete.path");
		targetSrc = (String) ibatorConfiguration.getProperties().get("extends.dao.config.path");
		outPutName = "log4j.xml";
		templetName = "log4j.xml.ftl";


		try {
			genRule.genFile(shellCallback, rootMap, directForTemp, targetSrc, "", outPutName, templetName, warnings,
					configoverwrite);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		for (String project : projects) {
			shellCallback.refreshProject(project);
		}
	}

	/**
	 * Writes, or overwrites, the contents of the specified file
	 * 
	 * @param file
	 * @param content
	 */
	private void writeFile(File file, String content) throws IOException {
		BufferedWriter bw = new BufferedWriter(new FileWriter(file, false));
		bw.write(content);
		bw.close();
	}

	private File getUniqueFileName(File directory, String fileName) {
		File answer = null;

		// try up to 1000 times to generate a unique file name
		StringBuffer sb = new StringBuffer();
		for (int i = 1; i < 1000; i++) {
			sb.setLength(0);
			sb.append(fileName);
			sb.append('.');
			sb.append(i);

			File testFile = new File(directory, sb.toString());
			if (!testFile.exists()) {
				answer = testFile;
				break;
			}
		}

		if (answer == null) {
			throw new RuntimeException(Messages.getString("RuntimeError.3", directory.getAbsolutePath())); //$NON-NLS-1$
		}

		return answer;
	}
}
